function formatDate(
  date: Date,
  format: 'YYYY-MM-DD' | 'YYYY/MM/DD' | 'MM/DD/YYYY' = 'YYYY-MM-DD',
  isTimePart = false,
) {
  const zeroFill = (num: number) => (num < 10 ? '0' + num : num + '')
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()

  const dateParts = format.split(/-|\//)
  const dateStr = dateParts.reduce((acc, part) => {
    if (part === 'YYYY') {
      return acc.replace(part, year + '')
    } else if (part === 'MM') {
      return acc.replace(part, zeroFill(month))
    } else if (part === 'DD') {
      return acc.replace(part, zeroFill(day))
    } else {
      return acc
    }
  }, format)

  const timeStr = isTimePart
    ? ' ' +
      [date.getHours(), date.getMinutes(), date.getSeconds()]
        .map(zeroFill)
        .join(':')
    : ''
  return dateStr + timeStr
}

function addDate(date: Date, diff: number, unit: 'days' | 'months' | 'years') {
  const dateCopy = new Date(date)
  if (unit === 'days') {
    dateCopy.setDate(dateCopy.getDate() + diff)
  } else if (unit === 'months') {
    dateCopy.setMonth(dateCopy.getMonth() + diff)
  } else if (unit === 'years') {
    dateCopy.setFullYear(dateCopy.getFullYear() + diff)
  }
  return dateCopy
}

function getToday(format = 'YYYY-MM-DD' as const) {
  return formatDate(new Date(), format)
}

function getYesterday(format = 'YYYY-MM-DD' as const) {
  return formatDate(addDate(new Date(), -1, 'days'), format)
}

function getLastMonthToday(format = 'YYYY-MM-DD' as const) {
  return formatDate(addDate(new Date(), -1, 'months'), format)
}

function getLastYearToday(format = 'YYYY-MM-DD' as const) {
  return formatDate(addDate(new Date(), -1, 'years'), format)
}

export {
  getToday,
  getYesterday,
  getLastMonthToday,
  getLastYearToday,
  formatDate,
  addDate,
}
